//创建一个共享内存，使服务端能够向里面写入数据，客户端能够向里面读取数据
#include"common.hpp"

int main()
{
    //生成特殊值
    cout<<"生成特殊值key..."<<endl<<endl;
    int key = Getkey();
    //sleep(2);
    cout<<"key生成成功, key is:"<<key<<endl<<endl;

start:
    cout<<"服务端以写的方式打开管道文件中..."<<endl;
    int wfd=open(filename,O_WRONLY);
    if(wfd<0)
    {
        cout<<"error:"<<errno<<",strerror:"<<strerror(errno)<<endl;
        if(MakeFifo())goto start;
        else return 1;
    }
    else 
    {
        cout<<"命名管道文件已存在，正在为您打开..."<<endl;
    }

    //sleep(2);
    //1.开辟一块共享内存
    cout<<"开始为您开辟一份共享内存..."<<endl<<endl;
    //sleep(2);
    int shmid = shmget(key,size,IPC_CREAT | IPC_EXCL |0664);  // 默认权限必须给，不然不能用 作用：开辟一块物理内存：
    //判断  成功，shmid;  失败，shmid==-1
    if(shmid<0)
    {
        cout<<"错误码："<<errno<<",错误信息："<<strerror(errno)<<endl;
        return 1;
    }
    cout<<"成功开辟了一份共享内存,shmid:"<<shmid<<endl<<endl;

    //sleep(2);
    cout<<"开始为服务端将共享内存映射到地址空间..."<<endl;
    //进度条加载
    progress_bar();
    //2.将共享内存映射到地址空间,为地址空间取名为addr_arr
    char* addr_arr=(char*)shmat(shmid,nullptr,0);
    //判断  成功，ret==0;  失败，ret==-1
    // if(*(int*)addr_arr<0)
    // {
    //     cout<<"错误码："<<errno<<",错误信息："<<strerror(errno)<<endl;
    //     return 1;
    // }
    cout<<"共享内存与地址空间映射成功！！"<<endl<<endl;

    cout<<"即将开始写入数据："<<endl;
    //sleep(3);
    //TODO
    char data='a';
    while(/*data<='z'*/true)
    {
        //int flag;
        sleep(1);
        //write(wfd,&flag,sizeof(flag));//通过命名管道来控制共享内存的“同步机制”

        cout<<"服务端写入数据:"<<addr_arr<<endl;
        //addr_arr[data-'a']=data;
        fgets(addr_arr,4096,stdin);
        //data++;
    }

    //3.解除共享内存与地址空间的映射关系
    int ret_dt = shmdt(addr_arr);
    //判断  成功，ret==0;  失败，ret==-1
    if(ret_dt<0)
    {
        cout<<"错误码："<<errno<<",错误信息："<<strerror(errno)<<endl;
        return 1;
    }

    //4.删除指定的共享内存
    int ret_ctl=shmctl(shmid,IPC_RMID,nullptr);
    //判断  成功，ret==0;  失败，ret==-1
    if(ret_ctl<0)
    {
        cout<<"错误码："<<errno<<",错误信息："<<strerror(errno)<<endl;
        return 1;
    }

    close(wfd);

    return 0;
}